package learnDecorate.homeworkQiang;


import org.junit.Test;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author jiangfeng 2018/7/25 11:44
 *
 * •订单表存储充值订单状态 • 账户表存储⽤户余额 • 根据订单的唯⼀编号进⾏账户余额增加操作 • 幂等、乐观锁、事务
 */
public class Main {

	// 线程安全,以原子方式将当前值加1，注意：这里返回的是自增前的值。
	private static AtomicInteger version =  new AtomicInteger(0);

	@Test
	public void test(){
		Main main =new Main();
		Order order= new Order(1,0,10.0d);
		Account account = new Account("zhangsan",100.0d);
		// 执行下单
		main.order(order,account,version.getAndIncrement());
	}

	/**
	 * 下订单
	 * @param order 订单
	 * @param account 扣款账户
	 * @param version 版本
	 */
	public void order(Order order,Account account,int version){
		System.out.println("order:"+order+" account:"+account+" version:"+version);
		// 用乐观锁的版本控制下
		if(order.status==0 && version == Main.version.get() ){
			try {
				// tx.begin(); // 伪代码开启事务
				order.status = 1; // 修改订单状态
				account.money = account.money - order.expense; // 扣除金额
				// tx.commit(); // 	伪代码提交事务
			}catch(Exception e){
				// 发生异常，回滚在本事务中的操做
				//	tx.rollback();
			}
		}
		System.out.println("order:"+order+" account:"+account+" version:"+version);
	}

	/**
	 * 	订单类
	 */
	class Order {
		public Order(int id, int status, double expense) {
			this.id = id;
			this.status = status;
			this.expense = expense;
		}

		// 订单id
		private int id;
		// 0表示未支付订单,1表示支付订单
		private int status;
		// 订单花费金额
		private double expense;

		public int getId() {
			return id;
		}

		public void setId(int id) {
			this.id = id;
		}

		public int getStatus() {
			return status;
		}

		public void setStatus(int status) {
			this.status = status;
		}

		public double getExpense() {
			return expense;
		}

		public void setExpense(double expense) {
			this.expense = expense;
		}

		@Override
		public String toString() {
			return "Order{" +
					"id=" + id +
					", status=" + status +
					", expense=" + expense +
					'}';
		}
	}

	/**
	 * 账户类
	 */
	class Account {
		public Account(String user, double money) {
			this.user = user;
			this.money = money;
		}

		private String user;
		// 账户金额
		private double money;

		public String getUser() {
			return user;
		}

		public void setUser(String user) {
			this.user = user;
		}

		public double getMoney() {
			return money;
		}

		public void setMoney(double money) {
			this.money = money;
		}

		@Override
		public String toString() {
			return "Account{" +
					"user='" + user + '\'' +
					", money=" + money +
					'}';
		}
	}

}
